package club.kynb.mall.application.statemachine.order.action;


import club.kynb.mall.application.context.OrderContext;
import club.kynb.mall.application.model.model.command.RefundOrderCommand;
import club.kynb.mall.application.model.model.event.OrderApplyRefundEvent;
import club.kynb.mall.order.api.IOrderRefundService;
import club.kynb.mall.order.api.IOrderService;
import club.kynb.mall.order.constant.OrderEventEnum;
import club.kynb.mall.order.constant.OrderRefundStatusEnum;
import club.kynb.mall.order.constant.OrderStatusEnum;
import club.kynb.mall.order.model.dto.OrderDTO;
import club.kynb.mall.order.model.dto.OrderRefundDTO;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.pizza.common.web.exception.Errors;
import org.pizza.event.publish.EventBus;
import org.pizza.id.api.IdGenerator;
import org.pizza.statemachine.Action;
import org.springframework.stereotype.Component;
import org.springframework.transaction.support.TransactionTemplate;

import java.util.Optional;

/**
 * @author kynb_club@163.com
 * @since 2021/7/9 11:18 上午
 */
@Slf4j
@Component
@AllArgsConstructor
public class OrderRefundAction implements Action<OrderStatusEnum, OrderEventEnum, OrderContext> {
    private final IOrderService iOrderService;
    private final IOrderRefundService iOrderRefundService;
    private final IdGenerator idGenerator;
    private final TransactionTemplate transactionTemplate;
    private final EventBus eventBus;

    @Override
    public void execute(OrderStatusEnum from, OrderStatusEnum to, OrderEventEnum on, OrderContext orderContext) {
        final RefundOrderCommand command = (RefundOrderCommand) orderContext.getCommand();
        //检查订单状态
        final Optional<OrderDTO> orderOptional = iOrderService.getOrderBy(command.getInnerOrderNo());
        final OrderDTO orderDTO = orderOptional.orElseThrow(() -> Errors.BIZ.exception("传入订单编号有误，订单不存在"));
        transactionTemplate.executeWithoutResult(transactionStatus -> {
            //更新等待状态
            iOrderService.applyRefund(command.getInnerOrderNo());
            //生成退款申请记录
            iOrderRefundService.create(buildOrderRefund(orderDTO, command));
        });
        eventBus.publishEvent(OrderApplyRefundEvent.builder().innerOrderNo(command.getInnerOrderNo()).build());
    }

    private OrderRefundDTO buildOrderRefund(OrderDTO orderDTO, RefundOrderCommand command) {
        final OrderRefundDTO orderRefundDTO = new OrderRefundDTO();
        orderRefundDTO.setId(idGenerator.nextId(OrderRefundDTO.class));
        orderRefundDTO.setUserId(orderDTO.getUserId());
        orderRefundDTO.setAuditUserId(null);
        orderRefundDTO.setRefundNo(String.valueOf(orderRefundDTO.getId()));
        orderRefundDTO.setInnerOrderNo(orderDTO.getInnerOrderNo());
        orderRefundDTO.setFromOrderStatus(orderDTO.getOrderStatus());
        orderRefundDTO.setStatus(OrderRefundStatusEnum.PROCESSING.getStatus());
        orderRefundDTO.setType(1);
        orderRefundDTO.setRefundDesc(command.getRefundDesc());
        orderRefundDTO.setRefundAmount(orderDTO.getPayAmount());
        orderRefundDTO.setRemark("");
        orderRefundDTO.setExtension("");
        return orderRefundDTO;
    }

}
